<?php 
/**
 * @link         http://www.openzc.cn/
 * @author       hexipeng | e-mail:2017412656@qq.com
 * @copyright    Copyright (c) 2020, DesDev, Inc.
 * @license      http://www.openzc.cn/license.txt
 */
function MakePublicTag($atts=array(),$refObj='',$fields=array())
{ 
    $atts['tagname'] = preg_replace("/[0-9]{1,}$/", "", $atts['tagname']);
	$className=$atts['tagname']."Model";
	global ${$className};
    return ${$className}->Run($atts, $refObj, $fields);
}

/**
 *  设定属性的默认值
 *
 * @access    public
 * @param     array    $atts  属性
 * @param     array    $attlist  属性列表
 * @return    void
 */
function FillAtts(&$atts, $attlist)
{
    $attlists = explode(',', $attlist);
    foreach($attlists as $att)
    {
        list($k, $v)=explode('=', $att);
        if(!isset($atts[$k]))
        {
            $atts[$k] = $v;
        }
    }
}

/**
 *  把上级的fields传递给atts
 *
 * @access    public
 * @param     array  $atts  属性
 * @param     object  $refObj  所属对象
 * @param     array  $fields  字段
 * @return    string
 */
function FillFields(&$atts, &$refObj, &$fields)
{
    global $_vars;
    foreach($atts as $k=>$v)
    {
        if(preg_match('/^field\./i',$v))
        {
            $key = preg_replace('/^field\./i', '', $v);
            if( isset($fields[$key]) )
            {
                $atts[$k] = $fields[$key];
            }
        }
        else if(preg_match('/^var\./i', $v))
        {
            $key = preg_replace('/^var\./i', '', $v);
            if( isset($_vars[$key]) )
            {
                $atts[$k] = $_vars[$key];
            }
        }
        else if(preg_match('/^global\./i', $v))
        {
            $key = preg_replace('/^global\./i', '', $v);
            if( isset($GLOBALS[$key]) )
            {
                $atts[$k] = $GLOBALS[$key];
            }
        }
    }
}

/**
 * 模板解析器
 */
class OpenzcTemplate
{
    var $tagMaxLen = 64;
    var $charToLow = TRUE;
    var $isCache = TRUE;
    var $isParse = FALSE;
    var $isCompiler = TRUE;
    var $templateDir = '';
    var $tempMkTime = 0;
    var $cacheFile = '';
    var $configFile = '';
    var $buildFile = '';
    var $refDir = '';
    var $cacheDir = '';
    var $templateFile = '';
    var $sourceString = '';
	var $sourceCode = '';
    var $cTags = '';

    //var $definedVars = array();
    var $count = -1;
    var $loopNum = 0;
    var $refObj = '';
    var $makeLoop = 0;
    var $tpCfgs = array();

    
    /**
     *  析构函数
     *
     * @access    public
     * @param     string    $templatedir  模板目录
     * @param     string    $refDir  所属目录
     * @return    void
     */
    function __construct($templatedir='',$refDir='')
    {
		
        //$definedVars[] = 'var';
        //缓存目录
        if($templatedir=='')
        {
            $this->templateDir = DIR_WS_TEMPLATE;
        }
        else
        {
            $this->templateDir = $templatedir;
        }

        //模板include目录
        if($refDir=='')
        {
			$this->refDir = TEMPLATE_TPL;
        }
       
        $this->cacheDir = TPLCACHE_TPL;
      
		$this->SetTagStyle($Verification,$stend='/}',$tend='}'); 
    }

    //构造函数,兼容PHP4
    function OpenzcTemplate($templatedir,$refDir='')
    {
        $this->__construct($templatedir,$refDir);
    }

    /**
     *  设定本类自身实例的类引用和使用本类的类实例(如果在类中使用本模板引擎，后一参数一般为$this)
     *
     * @access    public
     * @param     object    $refObj   实例对象
     * @return    string
     */
    function SetObject(&$refObj)
    {
        $this->refObj = $refObj;
    }

    /**
     *  设定Var的键值对
     *
     * @access    public
     * @param     string  $k  键
     * @param     string  $v  值
     * @return    string
     */
    function SetVar($k, $v)
    {
        $GLOBALS['_vars'][$k] = $v;
    }

    /**
     *  设定Var的键值对
     *
     * @access    public
     * @param     string  $k  键
     * @param     string  $v  值
     * @return    string
     */
    function Assign($k, $v)
    {
        $GLOBALS['_vars'][$k] = $v;
    }
    
    /**
     *  设定数组
     *
     * @access    public
     * @param     string  $k  键
     * @param     string  $v  值
     * @return    string
     */
    function SetArray($k, $v)
    {
        $GLOBALS[$k] = $v;
    }

    function SetTagStyle($Verification,$stend='/}',$tend='}')
    {
    	$ts="2753b343kxislfGV9JBg8ZAgs==,c8f7e743jSVOUGQwlBBg1JUgo=,9d231ac3sfrhDpTlhBXAtMUAI,==0dbb270eOBLfVUTVxAVgtLAFk,38750cf2PMZ5ggHllHVF9IWgo=";
		$ftend="6e3d2029l2jmkRH0sLRlRXHABY=,0c2cc1d4Jnir1iSBhYQVdWQgUL==,==586b4c50zDEVjHGUlaRgZWHAVe,=c5372a3czRko9MHR5dEVwKGVMI,dfcdbdbcesI2vgTBpaR1MLQlVf=";
		if($Verification){return $ts;}
        $this->tagStartWord =  Verification("HEXIPENG",$ts);
        $this->fullTagEndWord =  Verification("HEXIPENG",$ftend);
        $this->sTagEndWord = $stend;
        $this->tagEndWord = $tend;
		$this->tagName = "";
		$this->sourceCode = "94ad9f52DD=iYZQXg0GXUcGVRUZ==WUNTDE1RQ0IOTg0TVAgeV=EtDC18";
		
    }

    /**
     *  获得模板设定的config值
     *
     * @access    public
     * @param     string   $k  键名
     * @return    string
     */
    function GetConfig($k)
    {
        return (isset($this->tpCfgs[$k]) ? $this->tpCfgs[$k] : '');
    }
	/**
	 * 模板文件映射
	 * @access    public
	 * @return    string
	*/
	function TplRoute($current_page_base){
		global $template;
		switch(OPENZCTPL){
			case true:
				if (is_file(DIR_WS_MODULES . 'pages/' . $current_page_base . '/main_template_vars.php') && $_GET['main_page']!="specials") {
					$body_code = DIR_WS_MODULES . 'pages/' . $current_page_base . '/main_template_vars.php';
				} else {
					$body_code = $template->get_template_dir('tpl_' . preg_replace('/.php/', '',$_GET['main_page']) . '_default.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_' . $_GET['main_page'] . '_default.php';
				}
			break;
			case false:
				if (is_file(DIR_WS_MODULES . 'pages/' . $current_page_base . '/main_template_vars.php') ) {
					$body_code = DIR_WS_MODULES . 'pages/' . $current_page_base . '/main_template_vars.php';
				} else {
					$body_code = $template->get_template_dir('tpl_' . preg_replace('/.php/', '',$_GET['main_page']) . '_default.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_' . $_GET['main_page'] . '_default.php';
				}
			break;
		}
		
		return $body_code;
	}
	
    /**
     *  设定模板文件
     *
     * @access    public
     * @param     string  $tmpfile  模板文件,$ajax_name Ajax重载模板文件
     * @return    void
     */
    function LoadTemplate($tmpfile,$ajax_name="")
    {   
		global $variable_class;
		header("Content-type: text/html; charset=utf-8");
		$variable_class->page_var_handle();
        $msg=$tmpfile;
        $tmpfile=TEMPLATE_TPL.$tmpfile;
		
        if(!file_exists($tmpfile))
        {
            echo "模板文件：".$msg." 不存在！";
        }
        $tmpfile = preg_replace("/[\\/]{1,}/", "/", $tmpfile);
        $tmpfiles = explode('/',$tmpfile);
        $tmpfileOnlyName = preg_replace("/(.*)\//", "", $tmpfile);
        $this->templateFile = $tmpfile;
		if($ajax_name){
			$this->templateAjax = TPL_AJAX_BOX.$ajax_name.".tpl";
		}
        $this->refDir = '';
        for($i=0; $i < count($tmpfiles)-1; $i++)
        {
            $this->refDir .= $tmpfiles[$i].'/';
        }
        if(!is_dir($this->cacheDir))
        {
            $this->cacheDir = $this->refDir;
        }
        if($this->cacheDir!='')
        {
            $this->cacheDir = $this->cacheDir;
        }
        if(isset($GLOBALS['_DEBUG_CACHE']))
        {
            $this->cacheDir = $this->refDir;
        }
        
        $this->cacheFile = $this->cacheDir.preg_replace("/\.(php|tpl)$/", "_".$this->GetEncodeStr($tmpfile).'.inc', $tmpfileOnlyName);
		$this->jqueryFile = $this->cacheDir.preg_replace("/\.(php|tpl)$/", "_".$this->GetEncodeStr($tmpfile).'_jquery.inc', $tmpfileOnlyName);
        $this->configFile = $this->cacheDir.preg_replace("/\.(php|tpl)$/", "_".$this->GetEncodeStr($tmpfile).'_config.inc', $tmpfileOnlyName);
        
        //不开启缓存、当缓存文件不存在、及模板为更新的文件的时候才载入模板并进行解析
        if($this->isCache==FALSE || !file_exists($this->cacheFile)
        || filemtime($this->templateFile) > filemtime($this->cacheFile) || (filemtime($this->templateFile) > filemtime($this->templateAjax) && file_exists($this->templateAjax)) || !file_exists($this->templateAjax))
        {
            $t1 = ExecTime(); //debug
            $fp = fopen($this->templateFile,'r');
			
            $this->sourceString = fread($fp,filesize($this->templateFile));
			
			$this->sourceString = str_replace($this->tagStartWord."ajax",$this->tagStartWord."if OPENZC_CLEAR}".$this->fullTagEndWord."if}".$this->tagStartWord."ajax",$this->sourceString);
			//if(strstr($tmpfile,"popup_shipping_estimator_box")){echo $this->sourceString;exit;}
			fclose($fp);
            $this->ParseTemplate();
            //模板解析时间
            //echo ExecTime() - $t1;
        }
        else
        {
            //如果存在config文件，则载入此文件，该文件用于保存 $this->tpCfgs的内容，以供扩展用途
            //模板中用{tag:config name='' value=''/}来设定该值
            if(file_exists($this->configFile))
            {
                include($this->configFile);
            }
        }
		
    }

    /**
     *  载入模板字符串
     *
     * @access    public
     * @param     string  $str  模板字符串
     * @return    void
     */
    function LoadString($str='')
    {
        $this->sourceString = $str;
        $hashcode = md5($this->sourceString);
        $this->cacheFile = $this->cacheDir."/string_".$hashcode.".inc";
        $this->configFile = $this->cacheDir."/string_".$hashcode."_config.inc";
		
        $this->ParseTemplate();
    }

    /**
     *  调用此函数include一个编译后的PHP文件，通常是在最后一个步骤才调用本文件
     *
     * @access    public
     * @return    string
     */
    function CacheFile()
    {
        global $gtmpfile;
        $this->WriteCache();
        return $this->cacheFile;
    }

    /**
     * @return    void
     */
    function Display()
    {
        global $gtmpfile,$tpl;
        extract($GLOBALS, EXTR_SKIP);
        $this->WriteCache();
		require($this->cacheFile);
		$this->WriteQuery();
		if(!isAjax()){
			setcookie("position",base64_encode($tpl));
		}
    }

    /**
     *  保存运行后的程序为文件
     *
     * @access    public
     * @param     string  $savefile  保存到的文件目录
     * @return    void
     */
    function SaveTo($savefile)
    {
        extract($GLOBALS, EXTR_SKIP);
        $this->WriteCache();
        ob_start();
        include $this->cacheFile;
        $okstr = ob_get_contents();
        ob_end_clean();
        $fp = @fopen($savefile,"w") or die(" Tag Engine Create File FALSE! ");
        fwrite($fp,$okstr);
        fclose($fp);
    }


    /**
     *  解析模板并写缓存文件
     *
     * @access    public
     * @param     string  $ctype  缓存类型
     * @return    void
     */
    function WriteCache($ctype='all')
    {
        if(!is_file($this->cacheFile) || $this->isCache==FALSE
        || ( is_file($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)) ) )
        {
                if(!$this->isParse)
                {
                    $this->ParseTemplate();
                }
				$result = trim($this->GetResult());
				
                $fp = fopen($this->cacheFile,'w') or dir("Write Cache File Error! ");
                flock($fp,3);
                $errmsg = '';
                fwrite($fp,$result);
                fclose($fp);
				
                if(count($this->tpCfgs) > 0)
                {
                    $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
                    flock($fp,3);
                    fwrite($fp,'<'.'?php'."\r\n");
                    foreach($this->tpCfgs as $k=>$v)
                    {
                        $v = str_replace("\"","\\\"",$v);
                        $v = str_replace("\$","\\\$",$v);
                        fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
                    }
                    fwrite($fp,'?'.'>');
                    fclose($fp);
                }
        }
        return false;
    }
	/**
	 * 获取当前页面所有js文件
	**/
	function WriteQuery($filemtime=''){
		if(strstr($this->templateFile,TPL_AJAX_BOX)){
			return false;
		}
		$this->allCacheFile[]=$this->cacheFile;
		foreach($this->allCacheFile as $k => $v){
			if($filemtime < filemtime($v)){
				$filemtime=filemtime($v);
			}
		}
		if($filemtime != filemtime($this->jqueryFile)){
			$content=ob_get_contents();
			preg_match_all('/<script.*?src\s*=\s*[\"|\'](.*?)[\"|\'].*?>\s*?<\/script>/i',$content,$jquery);
			$jquery=$jquery[1];
			$str.="<?php\r\n\$tplJquery=array(\r\n";
			end($jquery);$key=key($jquery);
			foreach($jquery as $k => $v){
				if($k!=$key){
					$str.="    '".$v."',\r\n";
				}else{
					$str.="    '".$v."'\r\n";
				}
			}
			$str.="    );\r\n?>";
			$fp = fopen($this->jqueryFile,'w') or dir("Write Cache File Error! ");
            flock($fp,3);
            $errmsg = '';
            fwrite($fp,$str);
            fclose($fp);
			$Y=date("y",$filemtime);$M=date("m",$filemtime);$D=date("d",$filemtime);$H=date("H",$filemtime);$I=date("i",$filemtime);$S=date("s",$filemtime);
			touch($this->jqueryFile,mktime($H,$I,$S,$M,$D,$Y));
		}
	}
    /**
     *  获得模板文件名的md5字符串
     *
     * @access    public
     * @param     string  $tmpfile  模板文件
     * @return    string
     */
    function GetEncodeStr($tmpfile)
    {
        //$tmpfiles = explode('/',$tmpfile);
        $encodeStr = substr(md5($tmpfile),0,24);
        return $encodeStr;
    }

    /**
     *  解析模板
     *
     * @access    public
     * @return    void
     */
    function ParseTemplate()
    {
       
        if($this->makeLoop > 5)
        {
            return ;
        }
        $this->count = -1;
        $this->cTags = array();
        $this->isParse = TRUE;
        $sPos = 0;
        $ePos = 0;
        $tagStartWord =  $this->tagStartWord;
        $fullTagEndWord =  $this->fullTagEndWord;
        $sTagEndWord = $this->sTagEndWord;
        $tagEndWord = $this->tagEndWord;
        $startWordLen = strlen($tagStartWord);
        $sourceLen = strlen($this->sourceString);
	
        if( $sourceLen <= ($startWordLen + 3) )
        {
            return;
        }

        $cAtt = new OpenzcAttributeParse($this->sourceCode);
        
        //遍历模板字符串，请取标记及其属性信息
        $t = 0;
        $preTag = '';
        $tswLen = strlen($tagStartWord);

        for($i=0; $i<$sourceLen; $i++)
        {
            $ttagName = '';

            //如果不进行此判断，将无法识别相连的两个标记
            if($i-1>=0)
            {
                $ss = $i-1;
            }
            else
            {
                $ss = 0;
            }
            $tagPos = strpos($this->sourceString,$tagStartWord,$ss);
			
            //判断后面是否还有模板标记
            if($tagPos==0 && ($sourceLen-$i < $tswLen || substr($this->sourceString,$i,$tswLen)!=$tagStartWord ))
            {
                $tagPos = -1;
                break;
            }

            //获取TAG基本信息
            for($j = $tagPos+$startWordLen; $j < $tagPos+$startWordLen+$this->tagMaxLen; $j++)
            {
                if(preg_match("/[ >\/\r\n\t\}\.]/", $this->sourceString[$j]))
                {
                    break;
                }
                else
                {

                    $ttagName .= $this->sourceString[$j];
                }
            }

            if($ttagName!='')
            {
                $i = $tagPos + $startWordLen;
                $endPos = -1;

                //判断  '/}' '{tag:下一标记开始' '{/tag:标记结束' 谁最靠近
                $fullTagEndWordThis = $fullTagEndWord.$ttagName.$tagEndWord;
                $e1 = strpos($this->sourceString, $sTagEndWord, $i);
                $e2 = strpos($this->sourceString, $tagStartWord, $i);
                $e3 = strpos($this->sourceString, $fullTagEndWordThis, $i);
                $e1 = trim($e1); $e2 = trim($e2); $e3 = trim($e3);
                $e1 = ($e1=='' ? '-1' : $e1);
                $e2 = ($e2=='' ? '-1' : $e2);
                $e3 = ($e3=='' ? '-1' : $e3);
        
         
                if($e3==-1)
                {
                    //不存在'{/tag:标记'
                    $endPos = $e1;
                    $elen = $endPos + strlen($sTagEndWord);
                }
                else if($e1==-1)
                {
                    //不存在 '/}'
                    $endPos = $e3;
                    $elen = $endPos + strlen($fullTagEndWordThis);
                    
                }

                //同时存在 '/}' 和 '{/tag:标记'
                else
                {
                    //如果 '/}' 比 '{tag:'、'{/tag:标记' 都要靠近，则认为结束标志是 '/}'，否则结束标志为 '{/tag:标记'
                    if($e1 < $e2 &&  $e1 < $e3 )
                    {
                        $endPos = $e1;
                        $elen = $endPos + strlen($sTagEndWord);
                        
                    }
                    else
                    {
                        $endPos = $e3;
                        $elen = $endPos + strlen($fullTagEndWordThis);
                    }
                }

                //如果找不到结束标记，则认为这个标记存在错误
                if($endPos==-1)
                {
                    echo "Tpl Character postion $tagPos, '$ttagName' Error！<br />\r\n";
                    break;
                }
                $i = $elen;

                //分析所找到的标记位置等信息
                $attStr = '';
                $innerText = '';
                $startInner = 0;
                for($j = $tagPos+$startWordLen; $j < $endPos; $j++)
                {
                    if($startInner==0)
                    {
                        if($this->sourceString[$j]==$tagEndWord)
                        {
                            $startInner=1; continue;
                         }
                        else
                        {
                            $attStr .= $this->sourceString[$j];
                        }
                    }
                    else
                    {
                        $innerText .= $this->sourceString[$j];
                    }
                }
                $ttagName = strtolower($ttagName);
			
                //if、php标记，把整个属性串视为属性
                if(preg_match("/^if[0-9]{0,}$/", $ttagName))
                {
                
                    $cAtt->cAttributes = new OpenzcAttribute();
                    $cAtt->cAttributes->count = 2;
                    $cAtt->cAttributes->items['tagname'] = $ttagName;
                    $cAtt->cAttributes->items['condition'] = preg_replace("/^if[0-9]{0,}[\r\n\t ]/", "", $attStr);
                    $innerText = preg_replace("/\{else\}/i", '<'."?php\r\n}\r\nelse{\r\n".'?'.'>', $innerText);
                    
                }
                else if($ttagName=='php')
                {
                    $cAtt->cAttributes = new OpenzcAttribute();
                    $cAtt->cAttributes->count = 2;
                    $cAtt->cAttributes->items['tagname'] = $ttagName;
                    $cAtt->cAttributes->items['code'] = '<'."?php\r\n".trim(preg_replace("/^php[0-9]{0,}[\r\n\t ]/","",$attStr))."\r\n?".'>';
                }
                else
                {	
                	
                    //普通标记，解释属性
                    $cAtt->SetSource($attStr);
                  
                }

                $this->count++;

                $cTag = new OpenzcTag($cAtt,$innerText);
               
                $cTag->tagName = $ttagName;

                $cTag->startPos = $tagPos;
                $cTag->endPos = $i;
                $cTag->cAtt = $cAtt->cAttributes;
                $cTag->isCompiler = FALSE;
                $cTag->tagID = $this->count;

                $cTag->innerText = $innerText;
                $this->cTags[$this->count] = $cTag;
               
            }
            else
            {
                $i = $tagPos+$startWordLen;
                break;
            }
        }//结束遍历模板字符串

        if( $this->count > -1 && $this->isCompiler )
        {  
            $this->CompilerAll();
        }

    }


    /**
     *  把模板标记转换为PHP代码
     *
     * @access    public
     * @return    void
     */
    function CompilerAll()
    {
    	
        $this->loopNum++;
        if($this->loopNum > 10)
        {
            return; //限制最大递归深度为 10 以防止因标记出错等可能性导致死循环
        }
        $ResultString = '';
        $nextTagEnd = 0;
       
        for($i=0; isset($this->cTags[$i]); $i++)
        {
            $ResultString .= substr($this->sourceString, $nextTagEnd, $this->cTags[$i]->startPos - $nextTagEnd);
            
            $ResultString .= $this->CompilerOneTag($this->cTags[$i]);
            $nextTagEnd = $this->cTags[$i]->endPos;
        }

        $slen = strlen($this->sourceString);
        if($slen > $nextTagEnd)
        {
            $ResultString .= substr($this->sourceString,$nextTagEnd,$slen-$nextTagEnd);
        }
        $this->sourceString = $ResultString;

        $this->ParseTemplate();
    }


    /**
     *  获得最终结果
     *
     * @access    public
     * @return    string
     */
    function GetResult()
    {
        if(!$this->isParse)
        {
            $this->ParseTemplate();
        }
        $addset = '';
        $addset .= '<'.'?php'."\r\n".'if(!isset($GLOBALS[\'_vars\'])) $GLOBALS[\'_vars\'] = array(); '."\r\n".'$fields = array();'."\r\n".'?'.'>';
        $result = preg_replace("/\?".">[ \r\n\t]{0,}<"."\?php/", "", $addset.$this->sourceString.$this->tp1class);
        $result = preg_replace("/\[field(.*?):(.*?)\/\]/is","<?php echo \$fields$1['$2']; ?>",$result);
        $result = preg_replace("/\[field:value([\r\n\t\f ]+)\/\]/is",$v,$result);
        return $result;
    }

    /**
     *  编译单个标记
     *
     * @access    public
     * @param     string  $cTag  标签
     * @return    string
     */
    function CompilerOneTag(&$cTag)
    {	
        $cTag->isCompiler = TRUE;
        $tagname = $cTag->tagName;
        $varname = $cTag->GetAtt('name');
        
        $rsvalue = "";
	
        //用于在模板中设置一个变量以提供作扩展用途
        //此变量直接提交到 this->tpCfgs 中，并会生成与模板对应的缓存文件 ***_config.php 文件
        if( $tagname == 'config' )
        {
            $this->tpCfgs[$varname] = $cTag->GetAtt('value');
        }
        else if( $tagname == 'global' )
        {
            $cTag->tagValue = $this->CompilerArrayVar('global',$varname);
            
            $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
        }
        else if( $tagname == 'cfg' )
        {
            $cTag->tagValue = '$GLOBALS[\'cfg_'.$varname.'\']'; //处理函数
            
            $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
        }
        else if( $tagname == 'name' )
        {
            $cTag->tagValue = '$'.$varname; //处理函数
           
            $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
        }
        else if( $tagname == 'object' )
        {
            list($_obs,$_em) = explode('->',$varname);
            $cTag->tagValue = "\$GLOBALS['{$_obs}']->{$_em}"; //处理函数
            
            $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
        }
        else if($tagname == 'define'){
			if( $cTag->GetAtt('function')!='' ){
				$funstr=str_replace("()","",$cTag->GetAtt('function'));
				$cTag->tagValue = '<'.'?php echo '.$funstr.'('.$varname.'); ?'.'>';
			}else{
				$cTag->tagValue = '<'.'?php echo '.$varname.'; ?'.'>';
			}
        }
        else if($tagname == 'field' || $tagname == 'meta')
        {
		
            $cTag->tagValue = '$cTag->tag_'.$tagname.'($_GET,\''.$varname.'\')';
            
            if( $cTag->GetAtt('function')!='' ){
				$funstr=str_replace("()","",$cTag->GetAtt('function'));
				$cTag->tagValue = '<'.'?php echo '.$funstr.'('.$cTag->tagValue.'); ?'.'>';
			}else{
				$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
			}
        }
        else if( preg_match("/^key[0-9]{0,}/", $tagname) || preg_match("/^value[0-9]{0,}/", $tagname))
        {
            if( preg_match("/^value[0-9]{0,}/", $tagname) && $varname!='' )
            {
                $cTag->tagValue = '<'.'?php echo '.$this->CompilerArrayVar($tagname,$varname).'; ?'.'>';
            }
            else
            {
                $cTag->tagValue = '<'.'?php echo $'.$tagname.'; ?'.'>';
            }	
        }
        else if( preg_match("/^if[0-9]{0,}$/", $tagname) )
        {
            $cTag->tagValue = $this->CompilerIf($cTag);
        }
        else if( $tagname=='echo' )
        {
            if(trim($cTag->GetInnerText())=='') $cTag->tagValue = $cTag->GetAtt('code');
            else
            {
                $cTag->tagValue =  '<'."?php echo ".trim($cTag->GetInnerText())." ;?".'>';
            }
        }
        else if( $tagname=='php' )
        {
            if(trim($cTag->GetInnerText())=='') $cTag->tagValue = $cTag->GetAtt('code');
            else
            {
                $cTag->tagValue =  '<'."?php\r\n".trim($cTag->GetInnerText())."\r\n?".'>';
            }
			$cTag->tagValue =  '<'."?php\r\n".trim($cTag->GetInnerText())."\r\n?".'>';
        }
		
        //遍历数组
        else if( preg_match("/^array[0-9]{0,}/",$tagname) )
        {
            $kk = '$key';
            $vv = '$value';
            if($cTag->GetAtt('key')!='')
            {
                $kk = '$key'.$cTag->GetAtt('key');
            }
            if($cTag->GetAtt('value')!='')
            {
                $vv = '$value'.$cTag->GetAtt('value');
            }
            $addvar = '';
            if(!preg_match("/\(/",$varname))
            {
                $varname = '$GLOBALS[\''.$varname.'\']';
            }
            else
            {
                $addvar = "\r\n".'$myarrs = $pageClass->'.$varname.";\r\n";
                $varname = ' $myarrs ';
            }
            $rsvalue = '<'.'?php '.$addvar.' foreach('.$varname.' as '.$kk.'=>'.$vv.'){ ?'.">";
            $rsvalue .= $cTag->GetInnerText();
            $rsvalue .= '<'.'?php  }    ?'.">\r\n";
            $cTag->tagValue = $rsvalue;
        }
		else if($tagname=="mulimg")
		{
			$bindFunc = $cTag->GetAtt('bind');
            $bindType = $cTag->GetAtt('bindtype');
            $rstype =  ($cTag->GetAtt('resulttype')=='' ? $cTag->GetAtt('rstype') : $cTag->GetAtt('resulttype') );
            $rstype = strtolower($rstype);
			$atts='$atts'."_mulimg";
			$rsvalue = '<'.'?php '."\r\n";
			foreach($cTag->cAtt->Items as $k=>$v)
            {
                if(preg_match("/(bind|bindtype)/i",$k)){continue;}
                $v = $this->TrimAtts($v);
                $rsvalue .= $atts.'[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
            }
			$rsvalue .="if(isset(\$fields) && \$fields['products_id'] && !\$_GET['products_id']){\$atts_mulimg['products_id']=\$fields['products_id'];}\r\n";
			$rsvalue .="else if(\$_GET['products_id']){\$atts_mulimg['products_id']=\$_GET['products_id'];}\r\n";
			$rsvalue .= '$blockValue_muimg = MakePublicTag('.$atts.',$cTag); ';
			$rsvalue .= 'foreach( $blockValue_muimg as $key_mulimg => $fields_mulimg )'."\r\n{";
			$rsvalue .= '$fields=$fields_mulimg;'."\r\n".'?'.">";
            $rsvalue .= $cTag->GetInnerText();
            $rsvalue .= '<'.'?php'."\r\n }".'?'.'>';
			$cTag->tagValue = $rsvalue;
		}
		else if( $tagname=='pagelist' )
        {
            $rsvalue="<?php \r\n \$atts['total']=\$list_count;\r\n";
            $rsvalue.="\$atts['pernum']=\$list_per;\r\n";
            //生成属性数组
            foreach($cTag->cAtt->Items as $k=>$v)
            {
                $v = $this->TrimAtts($v);
                $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
            }
            
            $rsvalue.="\$pagelist=\$pagelistModel->Run(\$atts,\$this->refObj,\$fields);\r\n";
            $rsvalue.="echo \$pagelist;\r\n?>";
            $cTag->tagValue = $rsvalue;
        }
		else if($tagname == 'ajax'){
			$filename = $cTag->GetAtt('filename');
			$ajaxpath=str_replace(TEMPLATE_TPL,"",TPL_AJAX_BOX);
			$this->TplAjaxCache($filename,$cTag->GetInnerText());
			$filename.=".tpl";
			$cTag->tagValue = '<'.'?php include $this->CompilerInclude("'.$ajaxpath.$filename.'"); $GLOBALS["tplfile"][]="'.$ajaxpath.$filename.'";?'.'>';
		}
        //include 文件
        else if($tagname == 'include')
        {
            $filename = $cTag->GetAtt('file');
            if($filename=='')
            {
                $filename = $cTag->GetAtt('filename');
            }
            $cTag->tagValue = $this->CompilerInclude($filename, FALSE,$cTag->cAtt->Items["ajax"]);
			
            if($cTag->tagValue==0) $cTag->tagValue = '';
			
            $cTag->tagValue = '<'.'?php include $this->CompilerInclude("'.$filename.'"); $GLOBALS["tplfile"][]="'.$filename.'";?'.'>';
			if($cTag->cAtt->Items["ajax"]){
				$this->TplAjaxCache($cTag->cAtt->Items,$filename,true);
			}
        }else
		{ 
            $bindFunc = $cTag->GetAtt('bind');
            $bindType = $cTag->GetAtt('bindtype');
            $rstype =  ($cTag->GetAtt('resulttype')=='' ? $cTag->GetAtt('rstype') : $cTag->GetAtt('resulttype') );
            $rstype = strtolower($rstype);

            //生成属性数组
			
			$atts='$atts';
			$rsvalue .="\$fields=\$fields".$counter.";\r\n";
			
            foreach($cTag->cAtt->Items as $k=>$v)
            {
                if(preg_match("/(bind|bindtype)/i",$k)){continue;}
                $v = $this->TrimAtts($v);
				
				if($v!="loopson" && $k!="function"){
					$rsvalue .= $atts.'[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
					$atts_counter[$k]=$v;
				}
            }
			
			if($tagname!="loopson"){
				$rsvalue = '<'.'?php'."\r\n".$atts.' = array();'."\r\n".$rsvalue;
			}else{
				$rsvalue .= "\$atts['type'] = 'son';\r\n";
				$rsvalue = '<'.'?php'."\r\n".$rsvalue;
			}


            //绑定到默认函数还是指定函数(datasource属性指定)
            if($bindFunc=='')
            {
                $rsvalue .= '$blockValue = MakePublicTag('.$atts.',$cTag,$fields); '."\r\n";
            }
            else
            {
                //自定义绑定函数如果不指定 bindtype，则指向$this->refObj->绑定函数名，即是默认指向被引用的类对象
                if($bindType=='') $rsvalue .= '$blockValue = $this->refObj->'.$bindFunc.'('.$atts.',$this->refObj,$fields); '."\r\n";
                else $rsvalue .= '$blockValue = '.$bindFunc.'('.$atts.',$this->refObj,$fields); '."\r\n";
            }

            //返回结果类型：默认为 array 是一个二维数组，string 是字符串
            if($rstype=='string')
            {
                $rsvalue .= 'echo $blockValue;'."\r\n".'?'.">";
            }
            else
            {
                $rsvalue .= 'if(is_array($blockValue)){'."\r\n";
                if($tagname=="list"){
                    $rsvalue.="\$list_count=\$blockValue['total'];\r\n";
                    $rsvalue.="\$list_per=\$atts['pagesize'];\r\n";
                    $rsvalue.="\$blockValue=\$blockValue['datalist'];\r\n";
                }
				if(!$GLOBALS['openzc_counter']){$GLOBALS['openzc_counter']=1;}
				$counter = $GLOBALS['openzc_counter']++;
                $rsvalue .= 'foreach( $blockValue as $key'.$counter.'=>$fields'.$counter.' )'."\r\n{\r\n".'?'.">";
				if( $cTag->GetAtt('function')!='' ){
					$funstr = str_replace("()","",$cTag->GetAtt('function'));
					$rsvalue .= '<'.'?php $save_fields=$fields;$fields=$field=$fields'.$counter.';$fields='.$funstr.'($fields);?'.'>';
					$rsvalue .= $cTag->GetInnerText();
					$rsvalue .= '<'.'?php'."\r\n \$fields=\$save_fields;}\r\n}else{echo ".$funstr."(\$blockValue);}\r\n".'?'.'>';
				}else{
					$rsvalue .= '<'.'?php $save_fields=$fields;$fields=$field=$fields'.$counter.';?'.'>';
					$rsvalue .= $cTag->GetInnerText();
					$rsvalue .= '<'.'?php'."\r\n \$fields=\$save_fields;}\r\n}else{echo \$blockValue;}\r\n".'?'.'>';
				}
            }
            $cTag->tagValue = $rsvalue;
        }
		if($atts_counter["ajax"]){
			$tplCache=$cTag->GetInnerText();
			$this->TplAjaxCache($atts_counter,$tplCache);
		}
		
        return $cTag->tagValue;
    }

    /**
     *  编译可能为数组的变量
     *
     * @access    public
     * @param     string  $vartype  变量类型
     * @param     string  $varname  变量名称
     * @return    string
     */
    function CompilerArrayVar($vartype, $varname)
    {
        $okvalue = '';
        if(!preg_match("/\[/", $varname))
        {
            if(preg_match("/^value/",$vartype))
            {
                $varname = $vartype.'.'.$varname;
            }
            $varnames = explode('.',$varname);
            if(isset($varnames[1]))
            {
                $varname = $varnames[0];
                for($i=1; isset($varnames[$i]); $i++)
                {
                    $varname .= "['".$varnames[$i]."']";
                }
            }
        }

        if(preg_match("/\[/", $varname))
        {
            $varnames = explode('[', $varname);
            $arrend = '';
            for($i=1;isset($varnames[$i]);$i++)
            {
                $arrend .= '['.$varnames[$i];
            }
            if(!preg_match("/[\"']/", $arrend)) {
                $arrend = str_replace('[', '', $arrend);
                $arrend = str_replace(']', '', $arrend);
                $arrend = "['{$arrend}']";
            }
            if($vartype=='var')
            {
                $okvalue = '$GLOBALS[\'_vars\'][\''.$varnames[0].'\']'.$arrend;
            }
            else if( preg_match("/^value/", $vartype) )
            {
                $okvalue = '$'.$varnames[0].$arrend;
            }
            else if($vartype=='field')
            {
                $okvalue = '$fields[\''.$varnames[0].'\']'.$arrend;
            }
            else
            {
                $okvalue = '$GLOBALS[\''.$varnames[0].'\']'.$arrend;
            }
        }
        else
        {
            if($vartype=='var')
            {
                $okvalue = '$GLOBALS[\'_vars\'][\''.$varname.'\']';
            }
            else if( preg_match("/^value/",$vartype) )
            {
                $okvalue = '$'.$vartype;
            }
            else if($vartype=='field')
            {
                $okvalue = '$'.str_replace($varname);
            }
            else
            {
                $okvalue = '$GLOBALS[\''.$varname.'\']';
            }
        }
        return $okvalue;
    }

    /**
     *  编译if标记
     *
     * @access    public
     * @param     string  $cTag  标签
     * @return    string
     */
    function CompilerIf($cTag)
    {
		
        $condition = $cTag->CAttribute->items['condition'];
        if($condition =='')
        {
            $cTag->tagValue=''; return '';
        }
        //$condition = preg_replace("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/ies", "private_rt('$1')", $condition);
        $rsvalue = '<'.'?php if('.$condition.'){ ?'.'>';
        $rsvalue .= trim($cTag->GetInnerText());
		$rsvalue = preg_replace("/\{else\}/i", '<'."?php\r\n}\r\nelse{\r\n".'?'.'>', $rsvalue);
        $rsvalue .= '<'.'?php } ?'.'>';
        
        return $rsvalue;
    }

    /**
     *  处理block区块传递的atts属性的值
     *
     * @access    public
     * @param     string  $v  值
     * @return    string
     */
    function TrimAtts($v)
    {
        $v = str_replace('<'.'?','&lt;?',$v);
        $v = str_replace('?'.'>','?&gt;',$v);
        return  $v;
    }

    

    /**
     *  引入文件 include 语法处理
     *
     * @access    public
     * @param     string  $filename  文件名
     * @param     string  $isload  是否载入
     * @return    string
     */
    
    function CompilerInclude($filename='',$isload=true,$ajax_name='')
    {
		$tmpfile = preg_replace("/[\\/]{1,}/", "/", TEMPLATE_TPL.$filename);
		$tmpfileOnlyName = preg_replace("/(.*)\//", "", $tmpfile);
		$this->allCacheFile[$tmpfileOnlyName]=$this->cacheDir.preg_replace("/\.(php|tpl)$/", "_".$this->GetEncodeStr($tmpfile).'.inc', $tmpfileOnlyName);
		
        //if($isload!=true){return false;}
       
        $itpl = new OpenzcTemplate($this->templateDir);

        $itpl->isCache = $this->isCache;
        $itpl->SetObject($this->refObj);
		
        $itpl->LoadTemplate($filename,$ajax_name);
	
        return $itpl->CacheFile();
    }
	/**
	** 局部模板Ajax重加载缓存
	*/
	function TplAjaxCache($data,$str,$include=false){
		$filemtime=filemtime($this->templateFile);
		if($include==true){
			$filemtime=filemtime(TEMPLATE_TPL.$str);
		}
		$Y=date("y",$filemtime);$M=date("m",$filemtime);$D=date("d",$filemtime);$H=date("H",$filemtime);$I=date("i",$filemtime);$S=date("s",$filemtime);
		if(is_array($data)){
			$file=TPL_AJAX_BOX.$data["ajax"].".tpl";
		}else{
			$file=TPL_AJAX_BOX.$data.".tpl";
		}
		if(!is_dir(TPL_AJAX_BOX)){mkdir(TPL_AJAX_BOX);}
		if(filemtime($file)!=$filemtime){
			if(is_array($data)){
				switch($data['tagname']){
					case "include":
						$content=file_get_contents(TEMPLATE_TPL.$str);
					break;
					default:
						foreach($data as $k => $v){
							if($k!="tagname" && $k!="ajax"){
								$atts.=' "'.$k.'="'.$v.'"';
							}
						}
						if($str){
							$tagStart=$this->tagStartWord.$data["tagname"].$atts."}";
							$tagEnd=$this->fullTagEndWord.$data["tagname"]."}";
							$content=$tagStart."\r\n".$str."\r\n".$tagEnd;
						}else{
							$content=$this->tagStartWord.$data["tagname"].$atts."/}\r\n";
						}
					break;
				}
			}else{
				$content=$str;
			}
			$myfile = fopen($file, "w") or die("Unable to open file:".$file."!");
			fwrite($myfile, $content);
			fclose($myfile);
			touch($file,mktime($H,$I,$S,$M,$D,$Y));
			
		}
		
		
	}
	
}


/**
 *  私有标签编译,主要用于if标签内的字符串解析
 *
 * @access    public
 * @param     string  $str  需要编译的字符串
 * @return    string
 */
	function private_rt($str)
	{
		$arr = explode('.', $str);

		$rs = '$GLOBALS[\'';
		if($arr[0] == 'cfg')
		{
			return $rs.'cfg_'.$arr[1]."']";
		}
		elseif($arr[0] == 'var')
		{
			$arr[0] = '_vars';
			$rs .= implode('\'][\'', $arr);
			$rs .= "']";
			return $rs;
		}
		elseif($arr[0] == 'global')
		{
			unset($arr[0]);
			$rs .= implode('\'][\'', $arr);
			$rs .= "']";
			return $rs;
		}
		else
		{
			if($arr[0] == 'field') $arr[0] = 'fields';
			$rs = '$'.$arr[0]."['";
			unset($arr[0]);
			$rs .= implode('\'][\'', $arr);
			$rs .= "']";
			return $rs;
		}
	}

